package com.exam.service.Impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exam.dto.AddUserDto;
import com.exam.dto.LoginDto;
import com.exam.dto.RegisterDto;
import com.exam.entity.User;
import com.exam.entity.UserRole;
import com.exam.exception.BusinessException;
import com.exam.exception.CommonErrorCode;
import com.exam.mapper.UserMapper;
import com.exam.service.UserService;
import com.exam.vo.UserInfoVo;
import com.exam.utils.JwtUtils;
import com.exam.utils.SaltEncryption;
import com.exam.vo.PageResponse;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.exam.utils.CommonUtils.setLikeWrapper;
import static com.exam.vo.UserInfoVo.fromUser;

@Service
@RequiredArgsConstructor
public class UserServiceImpl  extends ServiceImpl<UserMapper, User> implements UserService {

    private final  UserMapper userMapper;


    /**
     * 注册用户
     *
     * @param registerDto 注册用户信息
     * @return 返回JWT令牌
     * @throws BusinessException 当用户名已存在时抛出业务异常
     */
    @Override
    public String register(RegisterDto registerDto) {
        // 检查用户名是否已存在
        if (!checkUsername(registerDto.getUsername())){
            // 用户名已存在
            //用户名存在
            throw new BusinessException(CommonErrorCode.E_100103);
        }

        // 生成盐值
        //盐值
        //生成唯一识别码
        String salt= UUID.randomUUID().toString().substring(0,6);

        // 对密码进行加密
        String newPwd= SaltEncryption.saltEncryption(registerDto.getPassword(),salt);

        // 创建用户对象
        User user=new User();

        // 将注册信息复制到用户对象中
        BeanUtils.copyProperties(registerDto,user);

        // 设置加密后的密码
        user.setPassword(newPwd);

        // 设置盐值
        user.setSalt(salt);

        // 设置角色ID
        user.setRoleId(1);

        // 设置创建时间
        user.setCreateDate(new Date());

        // 将用户信息插入数据库
        userMapper.insert(user);

        // 发放JWT令牌
        //发放token令牌
        return JwtUtils.createToken(user);
    }

    /**
     * 检查数据库中是否存在给定的用户名
     *
     * @param username 要检查的用户名
     * @return 如果不存在则返回true，否则返回false
     */
    @Override
    public Boolean checkUsername(String username) {
        //检查数据库中是否存在给定的用户名
        //如果不存在 查询结果小于1 返回true 否则返回false
        return userMapper.selectCount(new QueryWrapper<User>().eq("username",username))<1;
    }
    /**
     * 登录方法
     *
     * @param loginDto 登录信息
     * @return 返回JWT令牌
     * @throws BusinessException 当用户名不存在、密码错误或账号封禁时抛出业务异常
     */
    @Override
    public String login(LoginDto loginDto) {
        // 根据用户名查询用户信息
        User user=userMapper.selectOne(new QueryWrapper<User>().eq("username",loginDto.getUsername()));
        if (user==null){
            // 用户不存在
            throw new BusinessException(CommonErrorCode.E_100102);
        }
        // 使用用户的盐值对用户输入的密码进行加密
        String saltPassword=SaltEncryption.saltEncryption(loginDto.getPassword(),user.getSalt());
        // 对用户输入的密码加密后，对比数据库密码 并且用户的状态是正常的
        if (saltPassword.equals(user.getPassword())&&user.getStatus()==1){
            // 发放token令牌
            return JwtUtils.createToken(user);
        }else{
            // 密码错误 或者账号封禁
            throw new BusinessException(CommonErrorCode.E_100101);
        }


    }

    /**
     * 根据用户名、真实姓名、页码和每页数量获取用户信息
     *
     * @param loginName 用户名
     * @param trueName 真实姓名
     * @param pageNo 页码
     * @param pageSize 每页数量
     * @return 分页响应对象，包含用户信息列表和总记录数
     */
    @Override
    public PageResponse<UserInfoVo> getUser(String loginName, String trueName, Integer pageNo, Integer pageSize) {
        // 创建分页对象
        IPage<User> userPage = new Page<>(pageNo, pageSize);
        // 创建查询参数映射
        Map<String ,Object> queryParams=new HashMap<>();
        // 设置用户名查询条件
        queryParams.put("username",loginName);
        // 设置真实姓名查询条件
        queryParams.put("true_name",trueName);
        // 创建查询条件包装器
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        // 设置模糊查询条件
        setLikeWrapper(wrapper,queryParams);
        // 设置按角色ID降序、创建时间降序排序
        wrapper.orderByDesc("role_id","create_date");
        // 设置按状态升序排序
        wrapper.orderByAsc("status");
        // 执行分页查询
        userPage = userMapper.selectPage(userPage, wrapper);
        // 将查询结果转换为用户信息列表
        List<UserInfoVo> records=userPage.getRecords().stream().map(UserInfoVo::fromUser).collect(Collectors.toList());

        // 构建分页响应对象
        return PageResponse.<UserInfoVo>builder()
                .data(records)
                .total(userPage.getTotal())
                .build();
    }

    /**
     * 根据用户类型和用户ID对用户进行处理
     *
     * @param type 用户类型，整型
     * @param userIds 用户ID，多个ID用逗号分隔，字符串类型
     * @throws BusinessException 当用户类型不为1、2、3时抛出业务异常
     */
    @Override
    public void handlerUser(Integer type, String userIds) {
        // 转换成数组，用于获取需要操作的用户的id数组
        String [] ids=userIds.split(",");
        switch (type){
            case 1:
                // 如果用户类型为1，则调用updateUserStatus方法，将用户状态更新为1
                updateUserStatus(ids,1);
                break;
            case 2:
                // 如果用户类型为2，则调用updateUserStatus方法，将用户状态更新为2
                updateUserStatus(ids,2);
                break;
            case 3:
                // 如果用户类型为3，则遍历ids数组，对每个用户ID调用userMapper的deleteById方法，删除对应的用户
                for (String id: ids){
                    userMapper.deleteById(Integer.parseInt(id));
                }
                break;
            default:
                // 如果用户类型不为1、2、3，则抛出业务异常
                throw new BusinessException(CommonErrorCode.E_100105);
        }
    }


    /**
     * 更新用户状态
     *
     * @param ids 用户ID数组
     * @param status 用户状态
     */
    private void updateUserStatus(String [] ids,Integer status){
        for (String id:ids){
            //当前需要修改的用户
            User user=userMapper.selectById(Integer.parseInt(id));
            // 设置用户状态
            user.setStatus(status);
            // 更新用户信息
            userMapper.updateById(user);
        }
    }

    /**
     * 向数据库中添加用户
     *
     * @param userDto 用户信息对象
     */
    @Override
    public void addUser(AddUserDto userDto) {
        // 生成盐值
        //盐值
        String salt=UUID.randomUUID().toString().substring(0,6);

        // 对密码进行加密
        String newPwd=SaltEncryption.saltEncryption(userDto.getPassword(),salt);

        // 将用户信息对象转换为User对象
        User user=userDto.toUser();

        // 设置用户对象的密码、盐值和创建时间
        user.setPassword(newPwd);
        user.setSalt(salt);
        user.setCreateDate(new Date());

        // 将用户对象插入数据库
        userMapper.insert(user);
    }

    /**
     * 根据用户ID获取用户信息
     *
     * @param userId 用户ID
     * @return 返回用户信息对象
     */
    @Override
    public UserInfoVo getUserById(Integer userId) {
        // 调用userMapper的selectById方法，根据用户ID查询用户信息
        return fromUser(userMapper.selectById(userId));
    }

    /**
     * 根据用户ID列表获取用户信息
     *
     * @param userIds 用户ID列表
     * @return 用户信息列表
     */
    @Override
    public List<UserInfoVo> getUserInfoByIds(List<Integer> userIds) {
        // 调用userMapper的selectBatchIds方法，根据用户ID列表批量查询用户信息
        return userMapper.selectBatchIds(userIds).stream()
                // 将查询结果转换为UserInfoVo对象的流
                .map(UserInfoVo::fromUser)
                // 收集流中的元素，转换为列表返回
                .collect(Collectors.toList());
    }


}
